package com.example.blog.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.example.blog.domain.*;
import com.example.blog.mapper.UsersMapper;
import com.example.blog.service.LoginService;
import com.example.blog.utils.JwtUtils;
import com.example.blog.utils.RedisStorage;
import com.fasterxml.jackson.core.JsonProcessingException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;

import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;

//具体登录的实现
@Service
public class LoginServiceImpl implements LoginService {
    //注入security认证对象，这个bean在security中进行配置
    private final AuthenticationManager authenticationManager;
    private final RedisStorage redisStorage;
    private final UserInformationServiceImpl userInformationService;
    private final UsersMapper usersMapper;

    @Autowired
    LoginServiceImpl(UsersMapper usersMapper, UserInformationServiceImpl userInformationService, RedisStorage redisStorage, AuthenticationManager authenticationManager) {
        this.usersMapper = usersMapper;
        this.userInformationService = userInformationService;
        this.redisStorage = redisStorage;
        this.authenticationManager = authenticationManager;
    }

    @Override
    public Response login(Users users) throws JsonProcessingException {
        /*最核心的两句代码，用于security去认证，得到认证对象authentication*/
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(users.getUsername(), users.getPassword());
        Authentication authentication = authenticationManager.authenticate(authenticationToken);
      System.err.println(authentication);
        //如果用户没认证成功，给出相应的提示
        if (Objects.isNull(authentication)) {
            throw new RuntimeException("账号密码错误");
        }
        // 查询用户的id,而后查询出用户信息
        UserInformation user = userInformationService
                .getOne(
                        new QueryWrapper<UserInformation>()
                                .eq("uid",
                                        usersMapper.selectOne(new QueryWrapper<Users>().eq("username", users.getUsername())).getUid()
                                )

                );
        //写入最近登录信息
        UpdateWrapper<UserInformation> updateWrapper = new UpdateWrapper<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        updateWrapper.set("last_logon_time", sdf.format(new Date())).eq("uid", user.getUid());
        userInformationService.update(null, updateWrapper);
        if (user.getState() == -1) {
            return new Response(Response.ERROR_CODE, "该账号已注销", null);
        } else if (user.getState() == 0) {
            return new Response(Response.ERROR_CODE, "该账号已禁用", null);
        }
        //认证通过，生成jwt;
        String jwt = JwtUtils.createJwt(user);
        //获取权限存入redis
        redisStorage.setPermission(authentication.getAuthorities(), user.getUid());
        //把完整的用户信息存入redis,用户id,以及token
        redisStorage.recordLogins(new LoginUser(user.getUid(), jwt));
        Map<String, Object> map = new HashMap<>();
        map.put("token", jwt);
        map.put("user", user);
        return new Response(Response.SUCCEED_CODE, "登录成功", map);
    }


}
